/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <stdbool.h>

#include "apps.h"
#include "bme68xLibrary.h"
#include "bsec2.h"
#include "mw_log_conf.h"


typedef struct{
	char Dev_EUI[18];				//设备ID
	char temperature[10];			//温度
	char humidity[10];				//湿度
	char pressure[20];				//压力
	char gasres[20];					//气组
	char index[10];						
	char battery_vol[5];	//电池电压
	char card_id[10];				//卡号
	char soft_version[5];		//软件版本号
}relevant_data_s;


UTIL_TIMER_Object_t readBMETimer;
BME_Mode BME_mode = BME_688_PARALLEL;

bool BME_init = true;
bool BME_error = false;
uint8_t BME_iaqAccuracy = 0xff;
uint8_t BME_gas_index_temp = 0;
uint8_t BME_gasPercentage = 0xff;
uint8_t BME_stabilizationStatus = 0xff;
uint8_t BME_runInStatus = 0xff;
uint8_t BME_scanCycle = 2;
uint8_t BME_scanCycle_temp = 0;
uint8_t BME_numberOfProfile = 10;
uint8_t BME_gasEstimate[4];
uint16_t BME_IAQ = 0xffff;
uint16_t BME_staticIAQ = 0xffff;
uint16_t BME_co2Equivalent = 0xffff;
uint16_t BME_VOCEquivalent = 0xffff;
uint16_t BME_measDur = 140;
uint16_t tempProf[BME_NUMBER_OF_PROF_MAX] =
	{210, 280, 280, 350, 350, 280, 210, 140, 70, 140};
uint16_t mulProf[BME_NUMBER_OF_PROF_MAX] =
	{32, 2, 30, 2, 30, 32, 32, 32, 32, 32};
uint32_t BME_gasResistance[BME_NUMBER_OF_PROF_MAX];

bool BME_reset = false;
bool BME_runFlag = false;
uint8_t BME_address = 0x76;
uint16_t BME_gasTemperature = 0xffff;
uint16_t BME_rawTemperature = 0xffff;
uint16_t BME_gasPressure = 0xffff;
uint16_t BME_gasHumidity = 0xffff;
uint16_t BME_rawHumidity = 0xffff;
uint32_t BME_rawGas = 0xffffffff;
relevant_data_s rest_data;
uint32_t devAddr;
uint8_t UniqueId[8];
uint8_t joined_flg = 0;

extern I2C_HandleTypeDef hi2c2;

uint8_t tca6408a_addr = 0;   // Detected device address (shifted left)
uint8_t config;
uint8_t output_state = 0x00;

bme68xData data;


//Dev2_start
void BMESensor(void) {
  //	__HAL_RCC_GPIOA_CLK_ENABLE();
  //	HAL_I2C_MspInit(&hi2c2);
  //	MX_I2C2_Init();
  
    if (BME_init) {
      uint8_t dev = (0x76 << 1);
      if(HAL_I2C_IsDeviceReady(&hi2c1, dev, 4, 100) == HAL_OK) {
        printf("BME68x is Connected 0x76\r\n");
        BME_address = 0x76;
      }
      else {
        dev = (0x77 << 1);
        if(HAL_I2C_IsDeviceReady(&hi2c1, dev,4, 100) == HAL_OK) {
          printf("BME68x is Connected 0x77\r\n");
          BME_address = 0x77;
        }
        else {
          printf("BME68x is Disconnected\r\n");
          return;
        }
      }
      //used only for IAQ
      bsecSensor sensorList[] = {
              BSEC_OUTPUT_IAQ,
              BSEC_OUTPUT_STATIC_IAQ,
              BSEC_OUTPUT_CO2_EQUIVALENT,
              BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
              BSEC_OUTPUT_RAW_TEMPERATURE,
              BSEC_OUTPUT_RAW_PRESSURE,
              BSEC_OUTPUT_RAW_HUMIDITY,
              BSEC_OUTPUT_RAW_GAS,
              BSEC_OUTPUT_STABILIZATION_STATUS,
              BSEC_OUTPUT_RUN_IN_STATUS,
              BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
              BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
              BSEC_OUTPUT_GAS_PERCENTAGE
        };
  
      bsecSensor sensorListScan[] = {
          BSEC_OUTPUT_RAW_PRESSURE,
          BSEC_OUTPUT_RAW_TEMPERATURE,
          BSEC_OUTPUT_RAW_HUMIDITY,
          BSEC_OUTPUT_RAW_GAS,
          BSEC_OUTPUT_RAW_GAS_INDEX,
          BSEC_OUTPUT_GAS_ESTIMATE_1,
          BSEC_OUTPUT_GAS_ESTIMATE_2,
          BSEC_OUTPUT_GAS_ESTIMATE_3,
          BSEC_OUTPUT_GAS_ESTIMATE_4
      };
      
      if (BME_reset) {
        printf("softReset\r\n");
        softReset();
        checkBsecStatus();
        BME_reset = false;
      }
      
      bool rslt;
      switch (BME_mode) {
        case BME_688_ULP: {
          begin(BME_address, &hi2c1, 0);
          rslt = updateSubscription(sensorList, ARRAY_LEN(sensorList),
            BSEC_SAMPLE_RATE_ULP);
          BME_init = !rslt;
          printf("updateSubULP %d\r\n", rslt);
          attachCallback(newDataCallback);
          break;
        }
        case BME_688_LP: {
          begin(BME_address, &hi2c1, 0);
          rslt = updateSubscription(sensorList, ARRAY_LEN(sensorList),
            BSEC_SAMPLE_RATE_LP);
          BME_init = !rslt;
          printf("updateSubLP %d\r\n", rslt);
          attachCallback(newDataCallback);
          break;
        }
        case BME_688_PARALLEL: {
          printf("updateSubCOSTUME %d %d\r\n", rslt, BME_numberOfProfile);
          
          begin(BME_address, &hi2c1, 0);
          setTPH(BME68X_OS_2X, BME68X_OS_16X, BME68X_OS_1X);
          uint16_t sharedHeaterDur = BME_measDur -
            (getMeasDur(BME68X_PARALLEL_MODE) / 1000);
          setHeaterProf03(tempProf, mulProf, sharedHeaterDur,
            BME_numberOfProfile);
          setOpMode(BME68X_PARALLEL_MODE);
  
          UTIL_TIMER_Stop(&readBMETimer);
          UTIL_TIMER_SetPeriod(&readBMETimer,
            ((BME_measDur * mulProf[0]) - 5));
          UTIL_TIMER_Start(&readBMETimer);
          BME_init = false;
          break;
        }
        default:
          break;
      }
      return;
    }
    bme68xData data;
    uint8_t nFieldsLeft = 0;
    uint8_t flagFoo = 0;
    switch (BME_mode) {
      case BME_688_ULP: {
        printf("STARTY28\r\n");
        if (BME_run()) { // If new data is available
        }
        else {
          checkBsecStatus();
          BME_error = true;
          printf("BME Error\r\n");
        }
        break;
      }
      case BME_688_LP: {			
        if (BME_run()) { // If new data is available
        }
        else {
          checkBsecStatus();
          printf("BME Error\r\n");
        }
        
        break;
      }
      case BME_688_PARALLEL: {
        UTIL_TIMER_Stop(&readBMETimer);
        if (BME_gas_index_temp < 10) {
          BME_gas_index_temp++;
        }
        BME_runFlag = true;
        if (fetchData()) {
          do {
          nFieldsLeft = getData01(&data);
            if (data.status == NEW_GAS_MEAS) {
              BME_gasTemperature = (int)(data.temperature * 100);
              BME_gasHumidity = (int)(data.humidity * 100);
              BME_gasPressure = (int)(data.pressure) / 100;
              printf("data.temp: %d\r\n", (int)data.temperature);
              printf("data.pressure: %d\r\n", (int)(data.pressure) / 100);
              printf("data.humidity: %d\r\n", (int)(data.humidity * 100));
              printf("gas_resistance: %d\r\n", (int)data.gas_resistance);
              
              BME_gas_index_temp = (int)data.gas_index;
              printf("data.gas_index: %d\r\n", BME_gas_index_temp);
  
              BME_gasResistance[data.gas_index] =
                (int)data.gas_resistance;
              printf("heater Prof: %d\r\n", (int)tempProf[data.gas_index]);
              BME_runFlag = false;
            }
            else {
            }
          } while (nFieldsLeft);
        }
        else {
          printf("Parallel Error2: %d\r\n", BME_gas_index_temp);
        }
        if (BME_gas_index_temp < (BME_numberOfProfile - 1)) {
          UTIL_TIMER_SetPeriod(&readBMETimer,
            ((BME_measDur * mulProf[BME_gas_index_temp + 1]) - 10));
          UTIL_TIMER_Start(&readBMETimer);
          printf("readBMETimer2 for[%d]: %d\r\n", BME_gas_index_temp,
            BME_measDur * mulProf[BME_gas_index_temp + 1]);
        }
        else {
          BME_gas_index_temp = 0;
          UTIL_TIMER_Stop(&readBMETimer);
          UTIL_TIMER_SetPeriod(&readBMETimer,
            (uint32_t)((BME_measDur * mulProf[0] - 10)));
          MW_LOG(TS_ON, VLEVEL_L, "STARTY69\r\n");
          UTIL_TIMER_Start(&readBMETimer);
          MW_LOG(TS_ON, VLEVEL_H, "readBMETimer2 for[%d]: %d\r\n",
          BME_gas_index_temp,
            BME_measDur * mulProf[0]);
        }
        break;
      }
      default:
        break;
    }
  }
  
  static void readBMETimerEvent(void *context) {
    //1000000 = ULP 1010000 = LP 1100000 = CONT 1110000 = Default
    //APP_LOG(TS_ON, VLEVEL_H, "%s BMETimerEvent\r\n", TAB);
    UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_readBME), CFG_SEQ_Prio_0);
    if (BME_mode == BME_688_LP || BME_mode == BME_688_ULP) {
      UTIL_TIMER_Stop(&readBMETimer);
      UTIL_TIMER_Start(&readBMETimer);
    }
  }

  
void bme688_task()
{

#if defined(BME68X_SUPPORT) && (BME68X_SUPPORT)
    // Dev2_start
    // BME68X_Get_Sensordata(dev);
    /*
    if (!BME_init && BME_mode == BME_688_PARALLEL) {
      __HAL_RCC_GPIOA_CLK_ENABLE();
      HAL_I2C_MspInit(&hi2c2);
      MX_I2C2_Init();
      uint8_t nFieldsLeft = 0;
      bme68xData data;
      if (fetchData()) {
        do {
        nFieldsLeft = getData01(&data);
          if (data.status == NEW_GAS_MEAS) {
            BME_gasTemperature = (int)(data.temperature * 100);
            BME_gasHumidity = (int)(data.humidity * 100);
            BME_gasPressure = (int)(data.pressure) / 100;
            BME_rawGas = data.gas_resistance;
            LOG_DEBUG("data.temp: %d\r\n", (int)data.temperature);
            LOG_DEBUG("data.pressure: %d\r\n", (int)(data.pressure) / 100);
            LOG_DEBUG("data.humidity: %d\r\n", (int)(data.humidity * 100));
            LOG_DEBUG("gas_resistance: %d\r\n", (int)data.gas_resistance);
            LOG_DEBUG("data.gas_index: %d\r\n", (int)data.gas_index);
            LOG_DEBUG("heater Prof: %d\r\n", (int)tempProf[data.gas_index]);
          }
        } while (nFieldsLeft);
      }
    }
    */
    if (!BME_init &&
        BME_runFlag && BME_mode == BME_688_PARALLEL)
    {
        uint8_t nFieldsLeft = 0;
        bme68xData data;
        if (fetchData())
        {
            do
            {
                nFieldsLeft = getData01(&data);
                if (data.status == NEW_GAS_MEAS)
                {
                    BME_gasTemperature = (int)(data.temperature * 100);
                    BME_gasHumidity = (int)(data.humidity * 100);
                    BME_gasPressure = (int)(data.pressure) / 100;
                    LOG_DEBUG("data.temp: %d\r\n", (int)data.temperature);
                    LOG_DEBUG("data.pressure: %d\r\n", (int)(data.pressure) / 100);
                    LOG_DEBUG("data.humidity: %d\r\n", (int)(data.humidity * 100));
                    LOG_DEBUG("gas_resistance: %d\r\n", (int)data.gas_resistance);

                    BME_gas_index_temp = (int)data.gas_index;
                    LOG_DEBUG("data.gas_index: %d\r\n", BME_gas_index_temp);
                    BME_runFlag = false;

                    BME_gasResistance[data.gas_index] =
                        (int)data.gas_resistance;
                    LOG_DEBUG("heater Prof: %d\r\n", (int)tempProf[data.gas_index]);

                    if (BME_gas_index_temp < (BME_numberOfProfile - 1))
                    {
                        UTIL_TIMER_Stop(&readBMETimer);
                        UTIL_TIMER_SetPeriod(&readBMETimer,
                                             (uint32_t)((BME_measDur * mulProf[BME_gas_index_temp + 1]) - 10));
                        MW_LOG(TS_ON, VLEVEL_L, "STARTY30\r\n");
                        UTIL_TIMER_Start(&readBMETimer);
                        MW_LOG(TS_ON, VLEVEL_H, "readBMETimer2 for[%d]: %d\r\n",
                               BME_gas_index_temp,
                               BME_measDur * mulProf[BME_gas_index_temp + 1]);
                    }
                    else
                    {
                        BME_gas_index_temp = 0;
                        UTIL_TIMER_Stop(&readBMETimer);
                        UTIL_TIMER_SetPeriod(&readBMETimer,
                                             (uint32_t)(BME_measDur * mulProf[0]) - 10);
                        MW_LOG(TS_ON, VLEVEL_L, "STARTY51\r\n");
                        UTIL_TIMER_Start(&readBMETimer);
                        MW_LOG(TS_ON, VLEVEL_H, "readBMETimer2 for[%d]: %d\r\n",
                               BME_gas_index_temp,
                               BME_measDur * mulProf[0]);
                    }
                    /*sensor data copy to send buffer test*--------------*/
                    char hum_str[20], pre_str[20], res_str[20], tmp_str[20], inx_str[20];
                    sprintf(tmp_str, "%d", BME_gasTemperature);
                    memcpy(rest_data.temperature, tmp_str, strlen(tmp_str) + 1);

                    sprintf(hum_str, "%d", BME_gasHumidity);
                    memcpy(rest_data.humidity, hum_str, strlen(hum_str) + 1);

                    sprintf(pre_str, "%d", BME_gasPressure);
                    memcpy(rest_data.pressure, pre_str, strlen(pre_str) + 1);

                    sprintf(inx_str, "%d", BME_gas_index_temp);
                    memcpy(rest_data.index, inx_str, strlen(inx_str) + 1);

                    sprintf(res_str, "%d", (int)data.gas_resistance);
                    memcpy(rest_data.gasres, res_str, strlen(res_str) + 1);
                }
            } while (nFieldsLeft);
        }
    }
#endif    
}

struct bme68x_dev bme68xdev;

static void bme688_init(void){
    Init_BME68X(&bme68xdev);
    //Dev2_start
  	UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_readBME), UTIL_SEQ_RFU, BMESensor);
  	//readBMETimer
  	UTIL_TIMER_Create(&readBMETimer, 0xFFFFFFFFU, UTIL_TIMER_ONESHOT,
  		readBMETimerEvent, NULL);
    //Dev2_end
}

void app_init(const char * soft_version){
	printf("%s\r\n",soft_version);
	ldo_2v5_ctrl(1);
	//HAL_I2C_IsDeviceReady(&hi2c1, 0x54*2, 3, 100);
#if defined(BME68X_SUPPORT) && (BME68X_SUPPORT)
	bme688_init();
#endif
	bmv080_init();
}

/*
 *  113452	    492	   7300	 121244	  1d99c	STM32WLE5-Lora.elf  none
 * 165644	    732	  13404	 179780	  2be44	STM32WLE5-Lora.elf  lora,
 * 175868	    732	  33152	 209752	  33358	STM32WLE5-Lora.elf  lora + bmv080
 * 123684	    492	  27048	 151224	  24eb8	STM32WLE5-Lora.elf  bmv080
 * */

int app_task(void){
	bme688_task();
	bmv080_task();
	return 0;
}
